package mc2.ui;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.KeyStroke;

import de.waldemar.ChatIcons;
import de.waldemar.WindowUtils;

import mc2.*;

public class FrmChan extends javax.swing.JFrame {

  private boolean gotHistory = false;
  private volatile AtomicBoolean isBlinking = new AtomicBoolean(false);
  private FindDialog findDialog; 

  private class MyDispatcher implements KeyEventDispatcher {
    @Override
    public boolean dispatchKeyEvent(KeyEvent e) {
      if (e.getID() == KeyEvent.KEY_RELEASED) {
         if(e.isControlDown() && e.getKeyCode() == KeyEvent.VK_F) {
           findDialog.setVisible(true);
           findDialog.setLocation(msgArea.getLocationOnScreen());
         }
      }
      return false;
    }
  }

  /** Creates new form frmMain */
  public FrmChan() {
    
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    manager.addKeyEventDispatcher(new MyDispatcher());
    initComponents();
    findDialog = new FindDialog(this, msgArea);
    msgArea.setEditable(false);
    setMinimumSize(new Dimension(1000, 400));
    this.requestFocus();

    setIconImage(ChatIcons.ICON_DEFAULT);
    WindowUtils.optimizedCentrilized(this);
    typeBox.requestFocus();
  }

  public void dispose() {
    Manager.GetInstance().Quit();
  }

  /**
   * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
  private void initComponents() {
    nickPopup = new javax.swing.JPopupMenu();
    ppStartConv = new javax.swing.JMenuItem();
    ppShowShare = new javax.swing.JMenuItem();
    panSplit = new javax.swing.JSplitPane();
    jScrollPane1 = new javax.swing.JScrollPane();
    nickList = new javax.swing.JList();

    panRight = new javax.swing.JPanel();
    TextScroller = new javax.swing.JScrollPane();
    msgArea = new javax.swing.JTextArea();

    typeBox = new javax.swing.JTextField();

    toolbar = new javax.swing.JToolBar();
    btShare = new javax.swing.JToggleButton();
    tbSendFile = new javax.swing.JButton();
    btRecvFiles = new javax.swing.JButton();
    btClear = new javax.swing.JButton();
    chkAlwysOnTop = new JCheckBox("Allways On Top");
    chkAlwysOnTop.addItemListener(new ItemListener() {

      @Override
      public void itemStateChanged(ItemEvent e) {
        setAlwaysOnTop(chkAlwysOnTop.isSelected());
      }
    });
    chkPopupOnNewMessage = new JCheckBox("Popup on new Msg");
    cboPopupOnNewMessage = new JComboBox(new Object[] { filterAll });

    nickPopup.setInvoker(nickList);
    ppStartConv.setText("Private Conversation");
    ppStartConv.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        ppStartConvActionPerformed(evt);
      }
    });

    nickPopup.add(ppStartConv);

    ppShowShare.setText("Show Share");
    ppShowShare.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        ppShowShareActionPerformed(evt);
      }
    });

    nickPopup.add(ppShowShare);

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setTitle("Channel view");
    setName("frmMain");
    panSplit.setDividerLocation(100);
    panSplit.setPreferredSize(new java.awt.Dimension(200, 25));
    nickList.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mouseReleased(java.awt.event.MouseEvent evt) {
        nickListMouseReleased(evt);
      }
    });

    jScrollPane1.setViewportView(nickList);

    panSplit.setLeftComponent(jScrollPane1);

    panRight.setLayout(new java.awt.BorderLayout());

    TextScroller.setAutoscrolls(true);
    msgArea.setBackground(new java.awt.Color(229, 229, 249));
    msgArea.setColumns(20);
    msgArea.setRows(5);
    msgArea.setEditable(false);
    TextScroller.setViewportView(msgArea);

    panRight.add(TextScroller, java.awt.BorderLayout.CENTER);

    typeBox.addKeyListener(new java.awt.event.KeyAdapter() {
      public void keyPressed(java.awt.event.KeyEvent evt) {
        typeBoxKeyPressed(evt);
      }
    });

    nickList.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
          String curText = typeBox.getText();

          if (curText == null) {
            curText = "";
          }

          if (curText.length() > 0) {
            curText += " ";
          }

          curText += "@" + String.valueOf(nickList.getSelectedValue()) + " ";
          typeBox.setText(curText);
          typeBox.setCaretPosition(curText.length());
          typeBox.requestFocus();
        }
      }
    });

    panRight.add(typeBox, java.awt.BorderLayout.SOUTH);

    panSplit.setRightComponent(panRight);

    getContentPane().add(panSplit, java.awt.BorderLayout.CENTER);

    btShare.setText("Directory Sharing");
    btShare.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btShareActionPerformed(evt);
      }
    });

    toolbar.add(btShare);

    tbSendFile.setText("Send File");
    tbSendFile.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        tbSendFileActionPerformed(evt);
      }
    });

    toolbar.add(tbSendFile);

    btRecvFiles.setText("Received Files");
    btRecvFiles.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btRecvFilesActionPerformed(evt);
      }
    });

    toolbar.add(btRecvFiles);

    btClear.setText("Clear buffer");
    btClear.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btClearActionPerformed(evt);
      }
    });

    toolbar.add(btClear);
    toolbar.add(chkAlwysOnTop);
    toolbar.add(chkPopupOnNewMessage);
    toolbar.add(cboPopupOnNewMessage);

    getContentPane().add(toolbar, java.awt.BorderLayout.NORTH);

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void btClearActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btClearActionPerformed
    msgArea.setText("");
  }// GEN-LAST:event_btClearActionPerformed

  private void ppShowShareActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_ppShowShareActionPerformed
    if (nickList.getSelectedValue() != null && nickList.getSelectedValue() instanceof User)
      FrmUserShare.ForUser((User) (nickList.getSelectedValue())).Show();

  }// GEN-LAST:event_ppShowShareActionPerformed

  private void btShareActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btShareActionPerformed
    Manager.GetInstance().SetMyShare(btShare.isSelected());

  }// GEN-LAST:event_btShareActionPerformed

  private void tbSendFileActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tbSendFileActionPerformed
    Manager.GetInstance().SendFileToAll();
  }// GEN-LAST:event_tbSendFileActionPerformed

  private void btRecvFilesActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btRecvFilesActionPerformed
    Manager.GetInstance().ShowRecvFiles();
  }// GEN-LAST:event_btRecvFilesActionPerformed

  private void nickListMouseReleased(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_nickListMouseReleased
    if (evt.getButton() != evt.BUTTON1)
      nickPopup.show(nickList, evt.getX(), evt.getY());

  }// GEN-LAST:event_nickListMouseReleased

  private void ppStartConvActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_ppStartConvActionPerformed
    if (nickList.getSelectedValue() != null && nickList.getSelectedValue() instanceof User)
      Manager.GetInstance().StartPrivateConversation((User) (nickList.getSelectedValue()));

  }// GEN-LAST:event_ppStartConvActionPerformed

  private void typeBoxKeyPressed(java.awt.event.KeyEvent evt) {// GEN-FIRST:event_typeBoxKeyPressed
    if (evt.getKeyChar() == '\n')
      SendMsg();
  }// GEN-LAST:event_typeBoxKeyPressed

  public void UpdateNickList(User[] iUsers) {

    final User me = Manager.GetInstance().GetMe();
    Object selectedItem = cboPopupOnNewMessage.getSelectedItem();

    Vector<Object> vNicks = new Vector<Object>();
    vNicks.add(filterAll);
    for (User user : iUsers) {
      if (!user.equals(me)) {
        vNicks.add(user);
      }
    }

    cboPopupOnNewMessage.setModel(new DefaultComboBoxModel(vNicks));

    if (selectedItem == filterAll) {
      cboPopupOnNewMessage.setSelectedIndex(0);
    } else {
      for (int i = 0; i < vNicks.size(); i++) {
        if (selectedItem.equals(vNicks.get(i))) {
          cboPopupOnNewMessage.setSelectedIndex(i);
          break;
        }
      }
    }

    // Update List
    if (nickList.getModel() == null || !(nickList.getModel() instanceof NickListModel))
      nickList.setModel(new NickListModel(iUsers));
    ((NickListModel) nickList.getModel()).Update(iUsers);

    // Update History
    if (!gotHistory) {
      List<String> biggestHistory = new ArrayList<String>();

      for (User user : iUsers) {
        if (!me.equals(user)) {
          gotHistory = true;
          List<String> userHistory = user.getMsgHistory();
          if (userHistory.size() > biggestHistory.size()) {
            biggestHistory.clear();
            biggestHistory.addAll(userHistory);
          }
        }
      }

      for (String historyLine : biggestHistory) {
        AddRecvLine(historyLine);
      }
    }

  }

  public void SendMsg() {
    Manager.GetInstance().SendChanMessage(typeBox.getText());
    typeBox.setText("");
  }

  public void AddRecvLine(String iMsg) {
    msgArea.setText(msgArea.getText() + iMsg + "\n");
    msgArea.scrollRectToVisible(new Rectangle(0, msgArea.getHeight(), 1, 1));
    Manager.GetInstance().GetMe().addMsgHistory(iMsg);
  }

  public void handleReceiveEvent(String getName) {
    if (chkPopupOnNewMessage.isSelected()) {
      Object selUser = cboPopupOnNewMessage.getSelectedItem();
      if (selUser == filterAll) {
        setState(Frame.NORMAL);
      } else if (selUser instanceof User && ((User) selUser).GetName() != null) {
        if (((User) selUser).GetName().equals(getName)) {
          setState(Frame.NORMAL);
        }
      }
    }

    if (!isActive() && !isBlinking.get()) {
      isBlinking.set(true);
      new Thread() {

        public void run() {
          final String titleNotify = "****************************";
          final String titleOriginal = getTitle();
          while (!isActive()) {
            setIconImage(getIconImage() == ChatIcons.ICON_DEFAULT ? ChatIcons.ICON_ACTION : ChatIcons.ICON_DEFAULT);
            setTitle(getTitle().equals(titleOriginal) ? titleNotify : titleOriginal);
            try {
              Thread.sleep(500);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }

          setIconImage(ChatIcons.ICON_DEFAULT);
          setTitle(titleOriginal);

          synchronized (isBlinking) {
            isBlinking.set(false);
          }

        }
      }.start();
    }

  }

  public void ClearRecvArea() {
    msgArea.setText("");
  }

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JScrollPane TextScroller;
  private javax.swing.JButton btClear;
  private javax.swing.JButton btRecvFiles;
  private javax.swing.JToggleButton btShare;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JTextArea msgArea;
  private javax.swing.JList nickList;
  private javax.swing.JPopupMenu nickPopup;
  private javax.swing.JPanel panRight;
  private javax.swing.JSplitPane panSplit;
  private javax.swing.JMenuItem ppShowShare;
  private javax.swing.JMenuItem ppStartConv;
  private javax.swing.JButton tbSendFile;
  private javax.swing.JToolBar toolbar;
  private javax.swing.JTextField typeBox;
  private JCheckBox chkPopupOnNewMessage;
  private JCheckBox chkAlwysOnTop;
  private JComboBox cboPopupOnNewMessage;
  // End of variables declaration//GEN-END:variables
  private Object filterAll = new Object() {
    public String toString() {
      return "<All>";
    }
  };

}

class NickListModel extends javax.swing.AbstractListModel {
  User[] _nicklist;

  public NickListModel(User[] iList) {
    _nicklist = iList;
  }

  public int getSize() {
    return _nicklist.length;
  }

  public Object getElementAt(int i) {
    return _nicklist[i];
  }

  public void Update(User[] iList) {
    fireIntervalRemoved(this, 0, getSize());
    _nicklist = iList;
    fireIntervalAdded(this, 0, getSize());
  }
}